旅行商问题(TSP)及Python求解 您所在的位置:网站首页 python 最短路径 旅行商问题(TSP)及Python求解

旅行商问题(TSP)及Python求解

2023-03-12 08:47| 来源: 网络整理| 查看: 265

更新中...

我这学期就在研究路径优化。不知道大家是出于什么目的点进这篇文章,至少我有个心得就是只是copy代码的话反而浪费时间,其实一次把某个算法弄清楚反而是最快的学习方式......

旅行商问题可以说是路径优化的基础问题了,应该比较适合入门。把路径用图结构表示,然后用图论那一套解决,也是路径问题的基本操作了吧。接着遗传算法,它不仅是一个算法,它背后有一群算法,我习惯称它为动物园算法......

它们大致可分为两类,基于个体的和基于种群的,但核心思想都是一样的,不断迭代找到最优解,当然这个最优解是局部最优解,它最后不一定是全局最优解。

好了,开始:

旅行商问题(Traveling Salesman Problem, TSP)是指给定一个城市的集合以及每两个城市之间的距离,找到一条经过每个城市恰好一次且路径最短的回路。

可以想象成一个旅行商要拜访多个城市,问他如何安排路线,使得行程最短。这个问题可能看起来简单,但是随着城市数量的增加,计算量将呈指数级增长,所以TSP被认为是一个复杂的组合优化问题,也是计算复杂度理论中的NP难题之一。

ABCDEA04256B40323C23045D52403E63530

现在需要求解旅行商问题,即从任意一个城市出发,恰好经过每个城市一次,最终回到出发城市,使得旅行路径总长度最短。

图论求解:

import networkx as nx import itertools # 定义城市和距离矩阵 cities = ['A', 'B', 'C', 'D', 'E'] distances = [[0, 4, 2, 5, 6], [4, 0, 3, 2, 3], [2, 3, 0, 4, 5], [5, 2, 4, 0, 3], [6, 3, 5, 3, 0]] # 创建完全图 G = nx.Graph() G.add_nodes_from(cities) for i, j in itertools.combinations(range(len(cities)), 2): G.add_edge(cities[i], cities[j], weight=distances[i][j]) # 求解旅行商问题 shortest_tour = None min_tour_length = float('inf') for permutation in itertools.permutations(cities): tour_length = sum([G[permutation[i]][permutation[i+1]]['weight'] for i in range(len(cities)-1)]) tour_length += G[permutation[-1]][permutation[0]]['weight'] if tour_length < min_tour_length: shortest_tour = permutation min_tour_length = tour_length # 打印结果 print("最短旅行路径:", shortest_tour) print("路径长度:", min_tour_length)

输出结果:

遗传算法求解:

import numpy as np # 假设有5个城市,每个城市的编号分别为0, 1, 2, 3, 4 num_cities = 5 # 距离矩阵 distances = np.array([[0, 4, 2, 5, 6], [4, 0, 3, 2, 3], [2, 3, 0, 4, 5], [5, 2, 4, 0, 3], [6, 3, 5, 3, 0]]) # 定义遗传算法的参数 population_size =50 # 种群大小 mutation_rate = 0.02 # 变异概率 num_generations = 30 # 迭代次数 # 定义遗传算法的辅助函数 def create_individual(num_cities): # 生成一个随机的个体,即一条遍历所有城市的路径。 cities = list(range(num_cities)) individual = random.sample(cities, len(cities)) # 随机排列城市 return individual def calculate_fitness(individual, distances): # 计算一个个体的适应度,即遍历所有城市的路径长度。 fitness = 0 for i in range(len(individual)): if i == len(individual) - 1: # 如果当前城市是最后一个城市,则将其和起点城市相连 fitness += distances[individual[i]][individual[0]] else: # 否则将其和下一个城市相连 fitness += distances[individual[i]][individual[i+1]] return fitness def select_parents(population): # 选择父母个体。 parent_1 = random.choice(population) parent_2 = random.choice(population) while parent_1 == parent_2: # 如果两个父母个体是相同的,则重新选择第二个父母个体。 parent_2 = random.choice(population) return parent_1, parent_2 def crossover(parent_1, parent_2): # 交叉操作,产生新的后代个体。 crossover_point = random.randint(1, len(parent_1) - 1) child = parent_1[:crossover_point] + [city for city in parent_2 if city not in parent_1[:crossover_point]] return child #使用MDS算法将距离矩阵转化为坐标 def distance_to_coordinates(distance_matrix, num_dimensions=2): # 计算距离矩阵的平方 D = np.square(distance_matrix) # 对距离矩阵进行中心化 n = D.shape[0] I = np.eye(n) H = I - np.ones((n, n)) / n B = -1 / 2 * H @ D @ H # 对中心化后的距离矩阵进行特征值分解 eigvals, eigvecs = np.linalg.eigh(B) # 取特征值最大的k个特征值对应的特征向量作为新的坐标系 idx = np.argsort(eigvals)[::-1][:num_dimensions] W = eigvecs[:, idx] # 将每个城市的坐标表示为k个特征向量的线性组合 X = np.dot(W, np.sqrt(np.diag(eigvals[idx]))) return X city_locations = distance_to_coordinates(distances) # 绘制最优路径 def plot_best_route(best_individual): plt.plot(city_locations[:,0], city_locations[:,1], 'o') plt.plot(city_locations[best_individual,0], city_locations[best_individual,1], 'r') plt.plot([city_locations[best_individual[-1],0], city_locations[best_individual[0],0]], [city_locations[best_individual[-1],1], city_locations[best_individual[0],1]], 'r') plt.show() import random def mutate(individual, mutation_rate): # 以mutation_rate的概率对个体进行变异 if random.random() < mutation_rate: # 从个体中随机选择两个位置,并交换它们的值 swap_positions = random.sample(range(len(individual)), 2) individual[swap_positions[0]], individual[swap_positions[1]] = individual[swap_positions[1]], individual[swap_positions[0]] return individual # 主函数 def main(): # 初始化种群 population = [create_individual(num_cities) for i in range(population_size)] # 进化过程 for i in range(num_generations): # 计算种群中每个个体的适应度 fitness = [calculate_fitness(individual, distances) for individual in population] # 选择父母个体 parents = select_parents(population) # # 生成后代个体 # offspring = [crossover(parents[i], parents[i+1]) for i in range(0, population_size-1, 2)] # 生成后代个体 offspring = [crossover(parents[0], parents[1])] # 变异操作 offspring = [mutate(individual, mutation_rate) for individual in offspring] # 合并原始种群和后代个体 population = population + offspring # 计算新种群中每个个体的适应度 fitness = [calculate_fitness(individual, distances) for individual in population] # 选择适应度最好的前population_size个个体作为新种群 population = [population[i] for i in np.argsort(fitness)[:population_size]] # 输出每代中适应度最好的个体 print("Generation ", i, ": ", population[0], " (", fitness[0], ")") # 输出最优解 best_individual = population[0] best_fitness = calculate_fitness(best_individual, distances) print("Best individual: ", best_individual) #最优路径图 plot_best_route(best_individual) # plot_convergence_curve() if __name__ == "__main__": main()

输出结果:



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有